package com.hboxs.asl.wechat.utils;

import com.hboxs.asl.wechat.entity.WxConfig;
import com.hboxs.asl.wechat.entity.WxUserInfo;
import com.hboxs.asl.wechat.payment.UnifiedOrderResult;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.json.JSONTokener;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by study on 6/26/2015.
 */
public final class WechatUtils {

    private static final Logger logger = Logger.getLogger(WechatUtils.class);


    /* 作用域 */
//    /**
//     *
//     */
//    public static final String SNSAPI_LOGIN = "snsapi_login";
    /**
     * 不弹出授权页面，直接跳转，只能获取用户openid
     */
    public static final String SNSAPI_BASE = "snsapi_base";
    /**
     * 弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息
     */
    public static final String SNSAPI_USERINFO = "snsapi_userinfo";

    /* 媒体类型 */
    /**
     * 多媒体类型：图片
     */
    public static final String MEDIA_TYPE_IMAGE = "image";
    /**
     * 多媒体类型：语音
     */
    public static final String MEDIA_TYPE_VOICE = "voice";
    /**
     * 多媒体类型：视频
     */
    public static final String MEDIA_TYPE_VIDEO = "video";
    /**
     * 多媒体类型：缩略图
     */
    public static final String MEDIA_TYPE_THUMB = "thumb";

    /**
     * 不可实例化
     */
    private WechatUtils() {
    }

    /**
     * @param appid
     * @param redirect_uri
     * @param scope
     * @param state
     * @return
     */
    public static String wechatAuthUrl(String appid, String redirect_uri, String scope, String state) {
        String url = "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";

        url = String.format(url, appid, redirect_uri, scope, state);

        return url;
    }

    /**
     * @param appid
     * @param redirect_uri
     * @param scope
     * @param state
     * @return
     */
    public static String wechatLoginUrl(String appid, String redirect_uri, String scope, String state) {
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";

        url = String.format(url, appid, redirect_uri, scope, state);

        return url;
    }

    /**
     * @param appid  App Id
     * @param secret App Secret
     * @param code   Return Code
     * @return
     */
    public static JSONObject accessTokenUrl(String appid, String secret, String code) {
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

        url = String.format(url, appid, secret, code);
//        logger.info(url);
        JSONObject json = HttpClientUtils.get(url);
//        logger.info(json);
        return json;
    }

    /**
     * 公众平台获取 access token
     *
     * @param appid
     * @param secret
     * @return
     */
    public static WxConfig accessToken(String appid, String secret) {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";

        url = String.format(url, appid, secret);

        JSONObject json = HttpClientUtils.get(url);

        WxConfig wxConfig = new WxConfig();
        if (json.has("access_token")) {
            wxConfig.setConfigKey(WxConfig.KEY_ACCESS_TOKEN);
            wxConfig.setConfigValue(json.getString("access_token"));
            wxConfig.setExpiresIn(json.getInt("expires_in"));
        }

        return wxConfig;
    }


    /**
     * @param appid
     * @param refresh_token
     * @return
     */
    public static JSONObject refreashTokenUrl(String appid, String refresh_token) {
        String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";

        url = String.format(url, appid, refresh_token);

        JSONObject json = HttpClientUtils.get(url);

        return json;
    }

    public static JSONObject qrcode_creation(String access_token, JSONObject data) {
        String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s";

        url = String.format(url, access_token);

        JSONObject json = HttpClientUtils.post(url, data.toString());

        return json;
    }

    public static String qrcode(String ticket) {
        String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s";
        return String.format(url, ticket);
    }

    /**
     * 获取用户信息
     *
     * @param accessToken 关注时为系统accesstoken,未关注时为用户accesstoken
     * @param openid      用户openid
     * @param isSubscribe 是否关注
     * @return
     */
    public static WxUserInfo userinfo(String accessToken, String openid, boolean isSubscribe) {
        String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN";
        if (!isSubscribe) {
            url = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";
        }
        url = String.format(url, accessToken, openid);

        WxUserInfo wxUserInfo = null;
        try {
            JSONObject json = HttpClientUtils.get(url);

//            logger.info("User Info:" + json);
            wxUserInfo = new WxUserInfo();
            if (json.has("subscribe")) wxUserInfo.setSubscribe(json.getInt("subscribe"));
            if (json.has("openid")) wxUserInfo.setOpenid(json.getString("openid"));
            if (json.has("nickname")) wxUserInfo.setNickname(json.getString("nickname"));
            if (json.has("sex")) wxUserInfo.setSex(json.getInt("sex"));
            if (json.has("language")) wxUserInfo.setLanguage(json.getString("language"));
            if (json.has("city")) wxUserInfo.setCity(json.getString("city"));
            if (json.has("province")) wxUserInfo.setProvince(json.getString("province"));
            if (json.has("country")) wxUserInfo.setCountry(json.getString("country"));
            if (json.has("headimgurl")) wxUserInfo.setHeadimgurl(json.getString("headimgurl"));
            if (json.has("subscribe_time")) wxUserInfo.setSubscribe_time(json.getLong("subscribe_time"));
            if (json.has("unionid")) wxUserInfo.setUnionid(json.getString("unionid"));
            if (json.has("remark")) wxUserInfo.setRemark(json.getString("remark"));
            if (json.has("groupid")) wxUserInfo.setGroupid(json.getInt("groupid"));
            if (json.has("privilege")) wxUserInfo.setPrivilege(json.get("privilege").toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return wxUserInfo;
    }

    public static String uploadPermanentImage(String accessToken, BufferedImage image, String filename) {
        String mediaId = null;
        try {
            // 拼装请求地址
            String uploadMediaUrl = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=image";
            uploadMediaUrl = String.format(uploadMediaUrl, accessToken);
            URL url = new URL(uploadMediaUrl);
            String result = null;
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST"); // 以Post方式提交表单，默认get方式
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setUseCaches(false); // post方式不能使用缓存
            // 设置请求头信息
            con.setRequestProperty("Connection", "Keep-Alive");
            con.setRequestProperty("Charset", "UTF-8");
            // 设置边界
            String BOUNDARY = "----------" + System.currentTimeMillis();
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            // 请求正文信息
            // 第一部分：
            StringBuilder sb = new StringBuilder();
            sb.append("--"); // 必须多两道线
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"media\";filename=\"" + filename + "\" \r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");
            byte[] head = sb.toString().getBytes("utf-8");
            // 获得输出流
            OutputStream out = new DataOutputStream(con.getOutputStream());
            // 输出表头
            out.write(head);
            // 文件正文部分
            // 把文件已流文件的方式 推入到url中
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
            ImageIO.write(image, "jpg", ios);
            DataInputStream in = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            in.close();
            // 结尾部分
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
            out.write(foot);
            out.flush();
            out.close();
            StringBuffer buffer = new StringBuffer();
            BufferedReader reader = null;
            // 定义BufferedReader输入流来读取URL的响应
            reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            if (result == null) {
                result = buffer.toString();
            }
            // 使用JSON-lib解析返回结果
            JSONObject jsonObject = new JSONObject(result);
            if (jsonObject.has("media_id")) {
                mediaId = jsonObject.getString("media_id");
            } else {
                logger.info("None media_id key found:" + jsonObject.toString());
            }
        } catch (IOException e) {
            logger.error("发送POST请求出现异常！" + e);
        }

        return mediaId;
    }

    public static JSONObject sendTmplMsg(String accesstoken, JSONObject data) {
        String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
        try {
            url = String.format(url, accesstoken);

            JSONObject json = HttpClientUtils.post(url, data.toString());

            return json;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static JSONObject downloadMedia(String accesstoken, String mediaId) {
        String url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s";
        try {
            url = String.format(url, accesstoken, mediaId);
            URL urls = new URL(url);
            HttpURLConnection urlConnection = (HttpURLConnection) urls.openConnection();
            InputStream is = urlConnection.getInputStream();
            //Reader rd = new InputStreamReader(is, "utf-8");
            //JSONObject json = new JsonParser().parse(rd).getAsJsonObject();
            JSONObject json = new JSONObject(new JSONTokener(new InputStreamReader(is, "utf-8")));

            return json;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static UnifiedOrderResult submitUnifiedorder(JSONObject data) {
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        UnifiedOrderResult rst = null;
        try {
            url = String.format(url, data);

            JSONObject json = HttpClientUtils.post(url, data.toString());

            return rst;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 公众平台获取 jsapi ticket
     *
     * @param access_token
     * @return
     */
    public static WxConfig jsapiTicket(String access_token) {
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi";

        url = String.format(url, access_token);

        JSONObject json = HttpClientUtils.get(url);

        WxConfig wxConfig = new WxConfig();

        if (json.has("ticket")) {
            wxConfig.setConfigKey(WxConfig.KEY_JSAPI_TICKET);
            wxConfig.setConfigValue(json.getString("ticket"));
            wxConfig.setExpiresIn(json.getInt("expires_in"));
        }

        return wxConfig;
    }

}
